# coding=utf-8
import hashlib
import json
import string
import logging
import random
import time
from decimal import Decimal
import xmltodict
from pyexpat import ExpatError

from django.db import transaction
from django.http import HttpResponse
from wechatpy import WeChatPay, WeChatPayException
from wechatpy.pay import _check_signature
from wechatpy.pay.api import WeChatOrder, WeChatRefund
from worldcup.apps.userModel.models import PayDeal, UserUnion, OrderHead
from worldcup.commons.CommonResult import rest, CommonResult
from worldcup.commons.IdGenerator import generateId

logger = logging.getLogger('django')

APP_ID = "wx3d857b42797b5eb4"

API_KEY = "xz2X31GP1zfoSfOWq4gPqwDdaD6Ggl3Q"

MCH_ID = "1446925902"

weChatPay = WeChatPay(appid=APP_ID, api_key=API_KEY, mch_id=MCH_ID, mch_cert="/home/gmj/env/pay/apiclient_cert.p12",
					  mch_key="/home/gmj/env/pay/piclient_key.pem")

xcxWeChatPay = WeChatPay(appid='wxd93aedeb5302d03b', api_key='3e72a1c9d4b306f1de3f2dd079c04054', mch_id=MCH_ID)

order = WeChatOrder(client=weChatPay)

xcxOrder = WeChatOrder(client=xcxWeChatPay)

weChatRefund = WeChatRefund(client=weChatPay)


def sign_param(prepay_id):
	dict_param = {}
	dict_param["appId"] = "wxd93aedeb5302d03b"
	dict_param["timeStamp"] = int(time.time())
	dict_param["nonceStr"] = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(15))
	dict_param["package"] = "prepay_id=" + prepay_id
	dict_param["signType"] = "MD5"
	params = '&'.join(['%s=%s' % (key, dict_param[key]) for key in sorted(dict_param)])
	params = params + "&key=3e72a1c9d4b306f1de3f2dd079c04054"
	logger.info(params)
	dict_param["signature"] = hashlib.md5(params).hexdigest().upper()
	logger.info(dict_param["signature"])
	return dict_param


# @rest
# def prepay(request):
# 	"""
# 	微信统一支付
# 	"""
# 	try:
# 		reqest_params = json.loads(request.body)
# 	except ValueError:
# 		return CommonResult(-1, "数据格式错误")
# 	total_fee = reqest_params["totalFee"]
# 	if total_fee == "" or total_fee is None:
# 		return CommonResult(-1, "totalFee不能为空")
# 	# 金额转换为分
# 	total_fee = str((Decimal(100) * Decimal(total_fee)).quantize(Decimal('0')))
# 	user_id = reqest_params["openid"]
# 	if user_id == "" or user_id is None:
# 		return CommonResult(-1, "user_id不能为空")
# 	out_trade_no = reqest_params.get("outTradeNo")
# 	if out_trade_no is None:
# 		out_trade_no = generateId()
# 	try:
# 		# todo 判断小程序 or 公众号
# 		# data = order.create(trade_type="JSAPI", body="足球", total_fee=total_fee, out_trade_no=out_trade_no, user_id=user_id,
# 		# 				notify_url="https://worldcup.dmpb.com.cn/api/pay/notify")
# 		mini_openid = UserUnion.objects.filter(openid=user_id).get().mini_openid
# 		data = xcxOrder.create(trade_type="JSAPI", body="足球", total_fee=total_fee, out_trade_no=out_trade_no,
# 							user_id=mini_openid, notify_url="https://worldcup.dmpb.com.cn/api/pay/notify")
# 	except WeChatPayException, e:
# 		logger.error(e)
# 		return CommonResult(-1, e.message)
# 	prepay_id = data["prepay_id"]
# 	# 记录下单流水
# 	trade_id = generateId()
# 	paydeal = PayDeal(trade_id=trade_id, openid=user_id, prepay_id=prepay_id, order_id=out_trade_no,
# 					  request_amount=total_fee, pay_status=1, operate_status=1, created_at=int(time.time()),
# 					  updated_at=int(time.time()))
# 	paydeal.save()
#
# 	# sign
# 	result = sign_param(prepay_id)
# 	logger.info(result)
# 	return CommonResult(0, result)

@transaction.atomic
def notify(request):
	"""
	微信支付回调
	"""
	result = {}
	try:
		data = xmltodict.parse(request.body)['xml']
	except (xmltodict.ParsingInterrupted, ExpatError):
		# 解析 XML 失败
		logger.error('WeChat payment result xml parsing error', exc_info=True)
		return CommonResult(-1, "解析xml失败")
	return_code = data["return_code"]

	if return_code != "SUCCESS":
		logger.error("支付回调失败, " + data.get("return_msg"))
	if _check_signature(data, API_KEY):
		if data["result_code"] != "SUCCESS":
			logger.error("支付回调失败," + data["err_code_des"])
		out_trade_no = data["out_trade_no"]
		# 根据订单号获取paydeal记录
		pay_deal = PayDeal.objects.filter(order_id=out_trade_no).get()
		if pay_deal.pay_status == 3:
			logger.info("重复回调, order_id = " + out_trade_no)
		else:
			# pay_deal表
			pay_deal.pay_status = 3
			pay_deal.operate_status = 2
			# 微信支付单号
			pay_deal.transaction_id = data["transaction_id"]
			pay_deal.receive_amount = data["total_fee"]
			if str(pay_deal.receive_amount) != str(pay_deal.request_amount):
				logger.error("订单金额与支付金额不相等, order_id = {} , 订单金额 = {} , 支付金额 = {}".format(out_trade_no,
											pay_deal.request_amount, pay_deal.receive_amount))
				result["return_code"] = "FAIL"
				result["return_msg"] = "订单金额与支付金额不相等"
			else:
				pay_deal.time_end = data["time_end"]
				pay_deal.updated_at = int(time.time())
				pay_deal.save()

				# order表
				order_head = OrderHead.objects.filter(order_code=out_trade_no).get()
				order_head.order_status = 20
				order_head.pay_status = 20
				order_head.updated_at = int(time.time())
				order_head.save()

				result["return_code"] = "SUCCESS"
				result["return_msg"] = "OK"
	else:
		logger.info("wxpay notify checkSign is fail.")
		result["return_code"] = "FAIL"
		result["return_msg"] = "签名失败"

	# return_xml = xmltodict.unparse(input_dict={"xml": result})
	return_xml = "<xml><return_code><![CDATA[{}]]></return_code><return_msg><![CDATA[{}]]></return_msg></xml>".format(result["return_code"], result["return_msg"])
	logger.info("order_id = {} , 回调结果 = {}".format(out_trade_no, return_xml))
	response = HttpResponse(return_xml, content_type="application/xml")
	response["Access-Control-Allow-Origin"] = "*"
	response["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS"
	response["Access-Control-Max-Age"] = "1000"
	response["Access-Control-Allow-Headers"] = "*"
	return response


@rest
def refund(request):
	try:
		reqest_params = json.loads(request.body)
	except ValueError:
		return CommonResult(-1, "数据格式错误")
	refund_fee = reqest_params.GET.get("refundFee")
	if refund_fee == "" or refund_fee is None:
		return CommonResult(-1, "refund_fee不能为空")
	# 金额转换为分
	refund_fee = str((Decimal(100) * Decimal(refund_fee)).quantize(Decimal('0')))
	out_trade_no = reqest_params.GET.get("orderId")
	if out_trade_no == "" or out_trade_no is None:
		return CommonResult(-1, "orderId不能为空")
	# 查询此订单支付情况
	payDeal = PayDeal.objects.filter(order_id=out_trade_no).get()
	out_refund_no = generateId()

	try:
		res_data = weChatRefund.apply(total_fee=payDeal.receive_amount, refund_fee=refund_fee,
									  out_refund_no=out_refund_no,
									  out_trade_no=out_trade_no)
	except WeChatPayException, e:
		logger.error(e)
		return CommonResult(-1, e.message)
	# todo 入库

